package com.egao.common.module.push.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.egao.common.component.elasticsearch.entity.vo.ElasticPushMsgFormVO;
import com.egao.common.component.elasticsearch.service.ElasticSearchService;
import com.egao.common.component.elasticsearch.service.ElasticStatisticsService;
import com.egao.common.component.wechat.WeChatUtils;
import com.egao.common.core.web.JsonResult;
import com.egao.common.core.web.PageParam;
import com.egao.common.module.company.constants.CheckRecordConstants;
import com.egao.common.module.company.constants.CompanyConstants;
import com.egao.common.module.company.entity.*;
import com.egao.common.module.company.service.*;
import com.egao.common.module.company.utils.Address;
import com.egao.common.module.company.utils.AddressUtil;
import com.egao.common.module.company.utils.Job;
import com.egao.common.module.company.utils.JobUtil;
import com.egao.common.module.push.constants.PushConstants;
import com.egao.common.module.push.entity.*;
import com.egao.common.module.push.mapper.PushMsgMapper;
import com.egao.common.module.push.param.PushMsgParam;
import com.egao.common.module.push.service.PushMsgService;
import com.egao.common.module.push.vo.CollegeCountVO;
import com.egao.common.module.student.constants.StudentResumeConstants;
import com.egao.common.module.student.entity.Student;
import com.egao.common.module.student.entity.StudentResumeItem;
import com.egao.common.module.student.entity.vo.StudentPushVO;
import com.egao.common.module.student.mapper.StudentResumeItemMapper;
import com.egao.common.module.student.service.StudentService;
import com.egao.common.module.student.service.StudentSignService;
import com.egao.common.module.system.constants.DictConstants;
import com.egao.common.module.system.entity.Dict;
import com.egao.common.module.system.service.CollegeService;
import com.egao.common.module.system.service.DictService;
import com.egao.common.module.system.service.YearService;
import com.google.api.client.util.Joiner;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 消息推送表(PushMsg)表服务实现类
 *
 * @author dl
 * @since 2021-03-03 16:31:21
 */
@Service("pushMsgService")
@Slf4j
public class PushMsgServiceImpl extends ServiceImpl<PushMsgMapper, PushMsg> implements PushMsgService {

    @Autowired
    private StudentService studentService;

    @Autowired
    private DictService dictService;

    @Autowired
    private PositionService positionService;

    @Autowired
    private CompanyService companyService;

    @Autowired
    private ElasticStatisticsService elasticStatisticsService;

    @Autowired
    private ElasticSearchService elasticSearchService;

    @Autowired
    private StudentResumeItemMapper studentResumeItemMapper;

    @Autowired
    private StudentSignService studentSignService;

    @Autowired
    private PushMsgMapper pushMsgMapper;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private YearService yearService;

    @Autowired
    @Lazy
    private RecruitService recruitService;

    @Autowired
    @Lazy
    private PreachService preachService;

    @Autowired
    @Lazy
    private PreachCloudService preachCloudService;

    @Value("${service}")
    private String wechatUrl;
    /**
     * 单位性质
     */
    private List<Dict> natureList = null;
    /**
     * 单位行业
     */
    private List<Dict> industryList = null;
    /**
     * 规模
     */
    private List<Dict> scaleList = null;

    /**
     * 匹配度跨度
     */
    private Integer match = 10;

    /**
     * 动态表名前缀
     */
    private static String tableNamePrefix = "push_msg_";

    /**
     * old表名
     */
    private static String oldTableName = "push_msg";

    @Autowired
    private CollegeService collegeService;

    @Resource(name = "taskRunnerExecutor")
    private ExecutorService asyncExecutorService;


    @Override
    public List<PositionMatching> queryPositionMatchingByIds(AbilityFormDTO abilityFormDTO, Integer userId) {
        List<PositionMatching> positionMatchingList = new ArrayList<>();
        // 获取企业信息
        Company company = companyService.getByUserId(userId);
        // 获取希望匹配的职位id列表
        String ids = Joiner.on(',').join(abilityFormDTO.getIds());
        // 根据职位id列表获取职位列表
        List<Position> positions = positionService.getPositionByIds(ids);

        initDict();

        // 遍历职位列表
        for (Position position : positions) {
            // 拿到职位名和职位id放到职位匹配详情里
            PositionMatching positionMatching = new PositionMatching();
            positionMatching.setPositionName(position.getName());
            positionMatching.setPositionId(position.getId());

            // 根据职位专业查询对应专业学生 50分起
            List<Student> studentList = getStudentList(position.getMajor());
            if (studentList.size() == 0) {
                continue;
            }
            // 筛选没有毕业去向登记或登记待就业学生
            studentList = studentSignService.screenStudentSign(studentList);

            // 筛选能力条件
            studentList = abilityStudent(studentList, abilityFormDTO);

            // 一个职位N个学生匹配结果集合
            List<PositionMatchingFormVO> pmList = findPositionMatchingList(position, company, studentList);
            if (pmList.size() == 0) {
                positionMatchingList.add(positionMatching);
                continue;
            }

            int top = 100;
            // 最高分
            int max = 90;
            // 最低分
            int min = 85;

            int number = 1;
            long count100 = pmList.stream().filter(positionMatchingFormVO -> positionMatchingFormVO.getScore() == top).count();
            if (count100 > 0L) {
                positionMatching.setMatchingOne("100%");
                positionMatching.setMatchingOneValue(count100);
                positionMatching.setNumber(number++);
            }


            long count90 = pmList.stream().filter(positionMatchingFormVO -> positionMatchingFormVO.getScore() >= max).count();
            if (count90 > 0L) {
                if (number == 1) {
                    positionMatching.setMatchingOne("90%");
                    positionMatching.setMatchingOneValue(count90);
                    positionMatching.setNumber(number++);
                } else {
                    positionMatching.setMatchingTwo("90%");
                    positionMatching.setMatchingTwoValue(count90);
                    positionMatching.setNumber(number++);
                }

            }

            long count85 = pmList.stream().filter(positionMatchingFormVO -> positionMatchingFormVO.getScore() >= min).count();
            if (count85 > 0L) {
                if (number == 1) {
                    positionMatching.setMatchingOne("85%");
                    positionMatching.setMatchingOneValue(count85);
                    positionMatching.setNumber(number++);
                } else if (number == 2) {
                    positionMatching.setMatchingTwo("85%");
                    positionMatching.setMatchingTwoValue(count85);
                    positionMatching.setNumber(number++);
                } else {
                    positionMatching.setMatchingThree("85%");
                    positionMatching.setMatchingThreeValue(count85);
                    positionMatching.setNumber(number++);
                }
            }
            positionMatchingList.add(positionMatching);
        }

        return positionMatchingList;
    }

    @Override
    public void savePushMsg(String ids, PushMsg old, Integer userId, Integer businessId, AbilityFormDTO abilityFormDTO) {
        // 根据用户ID查找单位信息
        Company company = companyService.getByUserId(userId);
        List<Position> positions = positionService.getPositionByIds(ids);

        initDict();
        // 最后结果集合
        List<PositionMatchingFormVO> pmResultList = new ArrayList<>();
        for (Position position : positions) {

            // 根据职位专业查询对应专业学生 50分起
            List<Student> studentList = getStudentList(position.getMajor());
            // 筛选没有毕业去向登记或登记待就业学生
            studentList = studentSignService.screenStudentSign(studentList);
            // 筛选能力条件
            studentList = abilityStudent(studentList, abilityFormDTO);

            // 一个职位N个学生匹配结果集合
            List<PositionMatchingFormVO> pmList = findPositionMatchingList(position, company, studentList);
            if (pmList.size() == 0) {
                continue;
            }

            // 移除低于85分的匹配
            pmList.removeIf(positionMatchingFormVO -> positionMatchingFormVO.getScore() < 85);

            // 单位选择不推送 移除低于90分的匹配
            if ("1".equals(old.getCompanyFlag())) {
                pmList.removeIf(positionMatchingFormVO -> positionMatchingFormVO.getScore() < 90);
            }

            pmResultList.addAll(pmList);
        }

        List<PushMsg> pushMsgList = new ArrayList<>();
        List<Integer> studentList = new ArrayList<>();
        for (PositionMatchingFormVO pm : pmResultList) {
            Integer studentId = pm.getStudentId();
            // 去重复的学生
            if (studentList.contains(studentId)) {
                continue;
            }

            PushMsg pushMsg = new PushMsg();
            BeanUtil.copyProperties(old, pushMsg);
            pushMsg.setReadFlag(PushConstants.NO);
            pushMsg.setResumeFlag(PushConstants.NO);
            pushMsg.setPushType(PushConstants.NO);
            pushMsg.setStudentId(studentId);
            pushMsg.setYearId(pm.getYearId());
            pushMsg.setXh(pm.getXh());
            String positionMatching = "";
            List<Integer> matchingList = new ArrayList<>();
            for (PositionMatchingFormVO pm1 : pmResultList) {
                if (studentId.equals(pm1.getStudentId())) {
                    positionMatching += pm1.getPositionId() + "," + pm1.getScore() + "|";
                    matchingList.add(pm1.getScore());
                }
            }
            pushMsg.setMatching(Collections.max(matchingList).toString());
            pushMsg.setPositionMatching(positionMatching);
            pushMsgList.add(pushMsg);
            studentList.add(studentId);
        }

        // 根据年份动态插入数据
        for(PushMsg pushMsg : pushMsgList) {
            String tableName = tableNamePrefix + pushMsg.getYearId();
            dynamicInsertPushMsg(tableName, pushMsg);
        }

    }

    @Override
    @Deprecated
    public void push(Integer id, String title, String type, Date holdTime) {
        String typeName = "";
        String DM = wechatUrl;
        List<StudentPushVO> resultStudentList = new ArrayList<>();
        Integer year = yearService.getYear().getId();
        // 查询近三年的所有数据
        for (int i = 2; i >= 0; i--) {
            String tableName = tableNamePrefix + (year - i);
            resultStudentList.addAll(baseMapper.findStudentListByBusinessId(tableName, id, type));
        }
        // 兼容以前的库
        resultStudentList.addAll(baseMapper.findStudentListByBusinessId(oldTableName, id, type));
        List<PushMsg> msgs = new ArrayList<>();
        for (StudentPushVO student : resultStudentList) {
            String URL = "";
            String[] students = {student.getXh()};
            if ("1".equals(type)) {
                URL = "/mobile/matching/details/recruit?id=" + student.getId();
                typeName = "招聘信息";
            }
            if ("2".equals(type)) {
                URL = "/mobile/matching/details/prach?id=" + student.getId();
                typeName = "校内宣讲会";
            }
            if ("3".equals(type)) {
                URL = "/mobile/matching/details/cloud?id=" + student.getId();
                typeName = "空中宣讲会";
            }
            URL = DM + URL;

            String content = "(信息匹配度为:" + student.getMatching() + ")亲爱的同学，根据您的就业意向及专业等，现向您推荐【" + typeName + "】<a href=\"" + URL + "\">" + title + "</a>，请注意查看！<br>更多信息推荐请在微校园>万能广场>就业服务>信息推荐里查询";
            String abilityFlag = student.getAbilityFlag();
            if (PushConstants.YES.equals(abilityFlag)) {
                content = "亲爱的同学，根据您的简历信息，现向您推荐【" + typeName + "】<a href=\"" + URL + "\">" + title + "</a>，请注意查看！";
            }

            JsonResult result = WeChatUtils.push(students, content);
            // 保存结果
            PushMsg pushMsgContent = new PushMsg();
            if (result.getCode() == 0) {
                pushMsgContent.setPushType(PushConstants.YES);
                pushMsgContent.setPushContent(result.getData());
            } else {
                pushMsgContent.setPushContent(result.getMsg());
            }
            pushMsgContent.setTitle(title);
            // 管理员同意推送
            pushMsgContent.setAdminFlag(PushConstants.YES);
            // 设置推送消息编号
            pushMsgContent.setId(student.getId());
            pushMsgContent.setPushDate(new Date());
            pushMsgContent.setBusinessDate(holdTime);
            msgs.add(pushMsgContent);
        }
        if (msgs.size() > 0) {

            // 循环遍历并动态更新
            for (PushMsg pushMsg : msgs) {
                Integer y = studentService.getByUserId(pushMsg.getStudentId()).getYearId();
                String tableName = tableNamePrefix + y;
                dynamicUpdate(tableName, pushMsg);
            }

            // 兼容以前的更新
            updateBatchById(msgs);

            // 查询近几年的数据
            // PushMsg pushMsg = new PushMsg();
            // pushMsg.setType(type);
            // pushMsg.setBusinessId(id);
            // List<PushMsg> pushMsgList = selectManyYearsPushMsg(pushMsg);
            // List<PushMsg> pushMsgList1 = baseMapper.selectList(new QueryWrapper<PushMsg>().eq("type", type).eq("business_id", id));
            // elasticSearchService.savePushList(pushMsgList, id, type);
        }
    }

    @Override
    public void pushMsg() {
        List<PushMsg> msgList = getAllPushMsg();

        List<PushMsg> updateList = new ArrayList<>();

        Map<Integer, List<PushMsg>> map = msgList.stream().collect(Collectors.groupingBy(PushMsg::getStudentId));
        Set ketSet = map.keySet();
        for (Object key : ketSet) {
            List<PushMsg> pushMsgList = map.get(key);
            StringBuilder titles = new StringBuilder();
            int i = 1;
            String xh = "";
            for (PushMsg pushMsg : pushMsgList) {
                titles.append(i).append(".").append(pushMsg.getTitle()).append("<br>");
                i++;
                xh = pushMsg.getXh();

                // 保存结果
                PushMsg update = new PushMsg();
                update.setId(pushMsg.getId());
                update.setYearId(pushMsg.getYearId());
                update.setPushDate(new Date());
                update.setPushType("0");
                updateList.add(update);
            }

            String start = "亲爱的同学，根据您的就业意向，现向您推荐以下就业信息：<br>";
            String end = "更多信息推荐请在微校园>万能广场>就业服务>信息推荐里查询!";
            String content = start + titles + end;

            String url = wechatUrl + "/mobile/matching?xh=" + xh + "&today=0";
            content = "<a href=\"" + url + "\">" + content + "</a>";

            // 微信推送

            Student student = studentService.getById((int) key);
            // 学生接收推送, 不选默认接收推送
            if (!"0".equals(student.getPushState())) {
                String[] students = { xh };
                JsonResult result = WeChatUtils.push(students, content);
                if (result.getCode() != 0) {
                    Console.error("精准匹配信息推送失败：" + result.getMsg());
                }
            }

            if (CollectionUtil.isEmpty(updateList)) {
                return;
            }

            // 循环遍历并动态更新
            for (PushMsg pushMsg : updateList) {
                String tableName = tableNamePrefix + pushMsg.getYearId();
                try {
                    dynamicUpdate(tableName, pushMsg);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        try {
            Map<String, List<PushMsg>> esMap = msgList.stream().collect(Collectors.groupingBy(PushMsg::getType));
            Set esKetSet = map.keySet();
            for (Object key : esKetSet) {
                List<PushMsg> pushMsgList = esMap.get(key);

                Map<Integer, List<PushMsg>> buMap = pushMsgList.stream().collect(Collectors.groupingBy(PushMsg::getBusinessId));
                Set buKetSet = buMap.keySet();
                for (Object key1 : buKetSet) {
                    List<PushMsg> pushMsgList1 = esMap.get(key1);
                    elasticSearchService.savePushList(pushMsgList1, (Integer) key1, key.toString());
                }
            }
        } catch (Exception ex) {
            Console.error("精准匹配信息保存ES失败：" + ex.getMessage());
        }
    }



    @Override
    public void pushTomorrowPreach() {
        Date tomorrow = DateUtil.tomorrow();
        Date startDate = DateUtil.beginOfDay(tomorrow);
        Date endDate = DateUtil.endOfDay(tomorrow);
        String date = DateUtil.format(tomorrow, "yyyy-MM-dd");
        String DM = wechatUrl;

        List<StudentPushVO> resultStudentList = new ArrayList<>();
        Integer year = yearService.getYear().getId();
        // 查询近两年的所有数据
        for (int i = 1; i >= 0; i--) {
            String tableName = tableNamePrefix + (year - i);
            resultStudentList.addAll(baseMapper.listPreachStudentId(tableName, DateUtil.format(startDate, "yyyy-MM-dd HH:mm:ss"), DateUtil.format(endDate, "yyyy-MM-dd HH:mm:ss")));
        }
        // 兼容以前的库
        resultStudentList.addAll(baseMapper.listPreachStudentId(oldTableName, DateUtil.format(startDate, "yyyy-MM-dd HH:mm:ss"), DateUtil.format(endDate, "yyyy-MM-dd HH:mm:ss")));
        for (StudentPushVO student : resultStudentList) {
            String[] students = {student.getXh()};
            String URL = DM + "/mobile/matching/tomorrow?id="+student.getStudentId()+"date=" + date;
            String content = "亲爱的同学，根据您的就业意向及专业等，现向您推荐<a href=\"" + URL + "\">【明日举办宣讲会(" + date + ")】</a>，请注意查看！<br>更多信息推荐请在微校园>万能广场>就业服务>信息推荐里查询";
            JsonResult result = WeChatUtils.push(students, content);
            if (result.getCode() == 0) {
                System.out.println("明日宣讲会推送成功结果：" + result.getData());
            } else {
                System.out.println("明日宣讲会推送失败结果：" + result.getMsg());
            }
        }
    }


    @Override
    public Integer getPushCount(Integer businessId, String type) {
        return baseMapper.selectCount(new QueryWrapper<PushMsg>().eq("business_id", businessId).eq("type", type));
    }

    @Override
    public Integer getPushReadCount(Integer businessId, String type) {
        return baseMapper.selectCount(new QueryWrapper<PushMsg>().eq("business_id", businessId).eq("type", type).eq("read_flag", PushConstants.YES));
    }

    @Override
    public Integer getPushResumeCount(Integer businessId, String type) {
        return baseMapper.selectCount(new QueryWrapper<PushMsg>().eq("business_id", businessId).eq("type", type).eq("resume_flag", PushConstants.YES));
    }

    @Override
    public JsonResult countMessage(PageParam<ElasticPushMsgFormVO> pageParam) throws IOException {
        ElasticPushMsgFormVO pushMsgFormVO = new ElasticPushMsgFormVO();
        List<Position> positionNumberList = positionService.getPositionNumber();
        if (pageParam.get(PushConstants.APPLY_TIME) != null) {
            pushMsgFormVO.setApplyTime((String) pageParam.get(PushConstants.APPLY_TIME));
        }
        if (pageParam.get(PushConstants.COLLEGE_CODE) != null) {
            pushMsgFormVO.setCollegeCode((String) pageParam.get(PushConstants.COLLEGE_CODE));
        }
        if (pageParam.get(PushConstants.TYPE) != null) {
            pushMsgFormVO.setType((String) pageParam.get(PushConstants.TYPE));
        }
        if (pageParam.get(PushConstants.YEAR_ID) != null) {
            pushMsgFormVO.setYearId(Integer.parseInt(pageParam.get(PushConstants.YEAR_ID).toString()));
        }

        Map<String, Object> map = new HashMap<>();
        List<Map<String, Object>> provinceList = elasticStatisticsService.getListByKey(pushMsgFormVO, "province", 100);
        List<Map<String, Object>> natureList = elasticStatisticsService.getCompanyDict(pushMsgFormVO, "nature", DictConstants.COMPANY_NATURE);
        List<Map<String, Object>> industryList = elasticStatisticsService.getCompanyDict(pushMsgFormVO, "industry", DictConstants.COMPANY_INDUSTRY);
        List<Map<String, Object>> scaleList = elasticStatisticsService.getCompanyDict(pushMsgFormVO, "scale", DictConstants.COMPANY_SCALE);
        List<Map<String, Object>> collegeList = elasticStatisticsService.getListByKey(pushMsgFormVO, "collegeName", 100);
        List<Map<String, Object>> majorList = elasticStatisticsService.getListByKey(pushMsgFormVO, "majorName", 100);
        long positionTotal = elasticStatisticsService.pushPositionTotal(pushMsgFormVO);
        int positionSize = new Long(positionTotal == 0 ? 10 : positionTotal).intValue();
        List<Map<String, Object>> positionList = elasticStatisticsService.getPosition(pushMsgFormVO, positionSize);
        List<Map<String, Object>> positionTotalList = elasticStatisticsService.getListByKey(pushMsgFormVO, "positions.pId", positionSize);
        // 统计职位发布数量、招聘人数
        long positionRecruitTotal = 0;
        for (Map<String, Object> pos : positionTotalList) {
            String name = (String) pos.get("name");
            if (StrUtil.isNotBlank(name) || name.contains("p-")) {
                String idStr = name.replaceAll("p-", "");
                Integer id = Integer.parseInt(idStr);
                for (Position position : positionNumberList) {
                    if (position.getId().equals(id) && NumberUtil.isLong(position.getNumber())) {
                        positionRecruitTotal += Long.valueOf(position.getNumber());
                        break;
                    }
                }
            }
        }

        long total = elasticStatisticsService.pushCountTotal(pushMsgFormVO);
        long companyTotal = elasticStatisticsService.pushCompanyTotal(pushMsgFormVO);
        long studentTotal = elasticStatisticsService.pushStudentTotal(pushMsgFormVO);
        long readTotal = elasticStatisticsService.pushReadTotal(pushMsgFormVO);
        long readStudentTotal = elasticStatisticsService.pushReadStudentTotal(pushMsgFormVO);
        long resumeTotal = elasticStatisticsService.pushResumeTotal(pushMsgFormVO);
        long resumeStudentTotal = elasticStatisticsService.pushResumeStudentTotal(pushMsgFormVO);


        // 推荐总人次
        map.put("pushCountTotal", total);
        // 推荐阅读总数
        map.put("readTotal", readTotal);
        // 推荐阅读学生总数
        map.put("readStudentTotal", readStudentTotal);
        // 推荐总发送简历数
        map.put("resumeTotal", resumeTotal);
        // 推荐总发送简历学生数
        map.put("resumeStudentTotal", resumeStudentTotal);
        // 推荐信息接收学生总数
        map.put("studentTotal", studentTotal);
        // 推荐信息单位总数
        map.put("companyTotal", companyTotal);
        // 推荐信息职位总数
        map.put("positionTotal", positionTotal);
        // 推荐信息职位招聘总人数
        map.put("positionRecruitTotal", positionRecruitTotal);


        map.put("provinceList", provinceList);
        map.put("positionList", positionList);
        map.put("natureList", natureList);
        map.put("industryList", industryList);
        map.put("scaleList", scaleList);
        map.put("collegeList", collegeList);
        map.put("majorList", majorList);
        long pushBusinessTotal = 0;
        if (StrUtil.isBlank(pushMsgFormVO.getType())) {
            pushMsgFormVO.setType(CheckRecordConstants.CHECK_RECRUIT);
            pushBusinessTotal += elasticStatisticsService.pushBusinessTotal(pushMsgFormVO);
            pushMsgFormVO.setType(CheckRecordConstants.CHECK_PREACH);
            pushBusinessTotal += elasticStatisticsService.pushBusinessTotal(pushMsgFormVO);
            pushMsgFormVO.setType(CheckRecordConstants.CHECK_PREACH_CLOUD);
        }
        pushBusinessTotal += elasticStatisticsService.pushBusinessTotal(pushMsgFormVO);
        // 推荐信息总数
        map.put("businessTotal", pushBusinessTotal);
        return JsonResult.ok().setData(map);
    }

    @Override
    public void saveAbilityPushMsg(PushMsg old, String ids, Integer businessId) {
        return;
//        Map<String, Object> map = getMapByIds(ids);
//
//        if (StrUtil.isNotBlank(ids)) {
//            List<PushMsg> pushMsgList = new ArrayList<>();
//            List<Student> studentList = studentService.getStudentListByAbility(map);
//            for (Student student : studentList) {
//                PushMsg pushMsg = new PushMsg();
//                BeanUtil.copyProperties(old, pushMsg);
//                pushMsg.setReadFlag(PushConstants.NO);
//                pushMsg.setResumeFlag(PushConstants.NO);
//                pushMsg.setPushType(PushConstants.NO);
//                pushMsg.setStudentId(student.getId());
//                pushMsg.setYearId(student.getYearId());
//                pushMsg.setXh(student.getXh());
//                pushMsg.setAbilityFlag(PushConstants.YES);
//                pushMsgList.add(pushMsg);
//            }
//            if (pushMsgList.size() > 0) {
//                baseMapper.batchInsertAbility(pushMsgList);
//            }
//        }


    }

    /**
     * 根据选择能力推荐
     *
     * @param ids
     * @return
     */
    private Map<String, Object> getMapByIds(String ids) {
        Map<String, Object> map = new HashMap<>(16);
        String[] array = ids.split(",");
        for (String code : array) {
            switch (code) {
                case "1": {
                    map.put("basicQuality", StudentResumeConstants.ABILITY_YES);
                    break;
                }
                case "2": {
                    map.put("majorAbility", StudentResumeConstants.ABILITY_YES);
                    break;
                }
                case "3": {
                    map.put("basicAbility", StudentResumeConstants.ABILITY_YES);
                    break;
                }
                case "4": {
                    map.put("practiceAbility", StudentResumeConstants.ABILITY_YES);
                    break;
                }
                case "5": {
                    map.put("organizeAbility", StudentResumeConstants.ABILITY_YES);
                    break;
                }
                case "6": {
                    map.put("innovateAbility", StudentResumeConstants.ABILITY_YES);
                    break;
                }
                case "7": {
                    map.put("studyAbility", StudentResumeConstants.ABILITY_YES);
                    break;
                }
            }
        }
        return map;
    }

    /**
     * 验证月薪是否在范围内或对上 返回 true
     *
     * @param position
     * @param student
     * @return
     */
    public boolean verifySalary(Position position, Student student) {
        // 兼容以前的数据最大月薪和最低月薪匹配
        if (PushConstants.POSITION_SALARY_TYPE.equals(position.getSalaryType()) || PushConstants.STUDENT_SALARY_TYPE.equals(student.getIntenSalary())) {
            return true;
        }

        // 企业月薪和学生期望月薪匹配
        if (position.getSalary().equals(student.getSalary())) {
            return true;
        }

        if (StrUtil.isBlank(position.getSalaryType()) || StrUtil.isBlank(student.getIntenSalary())) {
            return false;
        }
        if (position.getSalaryMin() == null || position.getSalaryMax() == null || !student.getIntenSalary().contains(PushConstants.STUDENT_SALARY_SIGN)) {
            return false;
        }
        String[] ss = student.getIntenSalary().split(PushConstants.STUDENT_SALARY_SIGN);
        try {
            if (Integer.parseInt(ss[0]) >= position.getSalaryMin() && Integer.parseInt(ss[1]) <= position.getSalaryMax()) {
                return true;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return false;
    }

    /**
     * 计算学生与职位匹配度
     *
     * @param position
     * @param company
     * @param studentList
     * @return
     */
    private List<PositionMatchingFormVO> findPositionMatchingList(Position position, Company company, List<Student> studentList) {
        List<PositionMatchingFormVO> pmList = new ArrayList<>();

        for (Student student : studentList) {
            if (StrUtil.isBlank(student.getXl())) {
                continue;
            }
            if (StrUtil.isBlank(student.getIntenName())) {
                continue;
            }

            int i = 50;

            String xl = "无";
            switch (student.getXl()) {
                case "31":
                    xl = "本科";
                    break;
                case "11":
                    xl = "硕士";
                    break;
                case "01":
                    xl = "博士";
                    break;
            }

            if (StrUtil.isNotBlank(position.getDegree())
                    && StrUtil.isNotBlank(student.getXl())
                    && position.getDegree().contains(xl)) {
                i += 9;
            }

            // 获取地址集合
            List<Address> addressList = AddressUtil.getAddressList();

            // 根据学生的期望工作地址和企业的工作地址计算匹配度
            if (StrUtil.isNotBlank(position.getAddress())
                    && StrUtil.isNotBlank(student.getIntenAddress())) {
                String[] addressArr = student.getIntenAddress().split(",");

                // 遍历学生期望工作地点
                for (String address : addressArr) {
                    // 如果企业工作地点包含学生期望的工作地点就匹配正常
                    if (position.getAddress().contains(address)) {
                        i += 9;
                        break;
                    }
                    // 学生就业意愿是省的情况下，需要拿到当前省下的所有市去和企业工作地点去匹配
                    for(Address a : addressList) {
                        if (a.getName().equals(address) && a.getChildren() != null) {
                            boolean matchFound = a.getChildren().stream()
                                    .anyMatch(child -> position.getAddress().contains(child.getName()));
                            if (matchFound) {
                                i += 9;
                                break;
                            }
                        }
                    }
                }
            }


            if (verifySalary(position, student)) {
                i += 9;
            }

            if (StrUtil.isNotBlank(student.getIntenName()) && student.getIntenName().contains(position.getName())) {
                i += 8;
            }

            List<Job> jobs = JobUtil.getJobList();

            String[] studentIntenArr = student.getIntenName().split(",");

            for (String inten: studentIntenArr) {
                // 学生只有二级，企业有二三级，如果都是二级contains可以直接匹配上，这里只考虑企业三级学生二级的情况
                for (Job job: jobs) {
                    if (inten.equals(job.getValue()) && job.getItems() != null) {
                        for (Job j : job.getItems()) {
                            if (position.getName().equals(j.getValue())) {
                                i += 8;
                            }
                        }
                    }
                }
            }


            String nature = company != null ? company.getNature() != null ? company.getNature() : "" : "";

            if (StrUtil.isNotBlank(student.getIntenNature()) && student.getIntenNature().contains(getDictLabel(natureList, nature))) {
                i += 5;
            }
            String industry = company != null ? company.getIndustry() != null ? company.getIndustry() : "" : "";
            if (StrUtil.isNotBlank(student.getIntenIndustry()) && student.getIntenIndustry().contains(getDictLabel(industryList, industry))) {
                i += 5;
            }
            String scale = company != null ? company.getScale() != null ? company.getScale() : "" : "";
            if (StrUtil.isNotBlank(student.getIntenScale()) && student.getIntenScale().contains(getDictLabel(scaleList, scale))) {
                i += 5;
            }
            // 学生/职位/匹配度封装student.getId(), position.getId(), i
            PositionMatchingFormVO pm = new PositionMatchingFormVO();
            pm.setStudentId(student.getId());
            pm.setPositionId(position.getId());
            pm.setYearId(student.getYearId());
            pm.setScore(i);
            pm.setXh(student.getXh());
            pmList.add(pm);
        }
        return pmList;
    }

    @Override
    public JsonResult statisticsStudentPushByCollege(PageParam<ElasticPushMsgFormVO> pageParam) {
        try {
            return JsonResult.ok().setData(elasticStatisticsService.statisticsStudentPushByCollege(pageParam));
        } catch (IOException e) {
            log.error("统计各院精准匹配推送情况错误", e);
            return JsonResult.error("查询异常");
        }
    }

    /**
     * 获取字典字段的名称
     *
     * @param dictList 字典集合
     * @param value    字典值
     * @return
     * @date 2021/3/5 9:49
     */
    private String getDictLabel(List<Dict> dictList, String value) {
        for (Dict dict : dictList) {
            if (dict.getValue().equals(value)) {
                return dict.getLabel();
            }
        }
        return "";
    }

    /**
     * 初始化
     */
    private void initDict() {
        if (natureList == null) {
            natureList = dictService.cacheList(CompanyConstants.NATURE_LIST_TYPE);
        }

        if (industryList == null) {
            industryList = dictService.cacheList(CompanyConstants.INDUSTRY_LIST_TYPE);
        }

        if (scaleList == null) {
            scaleList = dictService.cacheList(CompanyConstants.SCALE_LIST_TYPE);
        }
    }

    /**
     * 根据专业查询学生，如果专业为不限，查询所有
     *
     * @param major 专业
     * @return
     */
    private List<Student> getStudentList(String major) {
        if (PushConstants.STUDENT_MAJOR_TYPE.equals(major)) {
            return studentService.getStudentListByMajors(null);
        } else {
            String[] majors = major.split(",");
            return studentService.getStudentListByMajors(Arrays.asList(majors));
        }
    }

    /**
     * 根据能力筛选学生
     *
     * @param studentList    学生集合
     * @param abilityFormDTO 能力参数
     * @return
     */
    private List<Student> abilityStudent(List<Student> studentList, AbilityFormDTO abilityFormDTO) {
        List<Student> removeList = new ArrayList<>();
        List<Integer> studentIds = new ArrayList<>();

        List<String> zzmmList = abilityFormDTO.getZzmm() != null ? abilityFormDTO.getZzmm() : new ArrayList<>();
        List<String> xlList = abilityFormDTO.getXl() != null ? abilityFormDTO.getXl() : new ArrayList<>();
        List<String> practiceList = abilityFormDTO.getPractice() != null ? abilityFormDTO.getPractice() : new ArrayList<>();
        List<String> honorList = abilityFormDTO.getHonor() != null ? abilityFormDTO.getHonor() : new ArrayList<>();
        List<String> jobList = abilityFormDTO.getJob() != null ? abilityFormDTO.getJob() : new ArrayList<>();
        List<String> certificateList = abilityFormDTO.getCertificate() != null ? abilityFormDTO.getCertificate() : new ArrayList<>();

        // 过滤政治面貌、学历
        for (Student item : studentList) {
            if (zzmmList.size() > 0 && !zzmmList.contains(item.getZzmm())) {
                removeList.add(item);
            }
            if (xlList.size() > 0 && !xlList.contains(item.getXl())) {
                removeList.add(item);
            }
        }
        studentList.removeAll(removeList);
        studentList.stream().forEach(item -> {
            studentIds.add(item.getId());
        });

        // 没有选择能力标签 直接返回学生数据
        if (practiceList.size() == 0 && honorList.size() == 0 && jobList.size() == 0 && certificateList.size() == 0) {
            return studentList;
        }


        List<Integer> saveIdList = new ArrayList<>();
        if (studentIds.size() > 0) {
            List<StudentResumeItem> studentResumeItemList = studentResumeItemMapper.listInStudent(studentIds);

            for (StudentResumeItem item : studentResumeItemList) {
                if (practiceList.size() > 0
                        && practiceList.contains("校外实践")
                        && item.getType().equals("1")
                        && !StrUtil.isBlank(item.getA2())
                        && !item.getA2().equals("无")
                ) {
                    saveIdList.add(item.getStudentId());
                }

                if (practiceList.size() > 0
                        && practiceList.contains("校外实践")
                        && item.getType().equals("2")
                        && !StrUtil.isBlank(item.getA2())
                        && !item.getA2().equals("无")
                ) {
                    saveIdList.add(item.getStudentId());
                }

                if (honorList.size() > 0
                && item.getType().equals("4")
                        && !StrUtil.isBlank(item.getA2())
                        && honorList.contains(item.getA2())
                ) {
                    saveIdList.add(item.getStudentId());
                }

                if (jobList.size() > 0
                        && item.getType().equals("5")
                        && !StrUtil.isBlank(item.getA2())
                        && jobList.contains(item.getA2())
                ) {
                    saveIdList.add(item.getStudentId());
                }

                for (String c : certificateList) {
                    if (StrUtil.isBlank(item.getA2())) {
                        saveIdList.remove(item.getStudentId());
                        continue;
                    }
                    if (c.equals(item.getA2())) {
                        saveIdList.add(item.getStudentId());
                    } else {
                        saveIdList.remove(item.getStudentId());
                    }
                }
            }

            // 这批学生中没有找到有能力标签的学生 返回空
            if (saveIdList.size() == 0) {
                return new ArrayList<Student>();
            }

            // 移除不匹配项
            removeList = new ArrayList<>();
            for (Student item : studentList) {
                boolean b = false;
                for (Integer id : saveIdList) {
                    if (item.getId().equals(id)) {
                        b = true;
                        break;
                    }
                }
                if (!b) {
                    removeList.add(item);
                }
            }
            studentList.removeAll(removeList);
            return studentList;
        }

        return new ArrayList<>();
    }

    /**
     * 检查表是否存在
     * @param tableName
     * @return
     */
    private boolean isTableExists(String tableName) {
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
            ResultSet resultSet = connection.getMetaData().getTables(null, null, tableName, null);
            return resultSet.next();
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 动态创建表
     * @param tableName
     */
    public void createTableNotExist(String tableName) {
        if (!isTableExists(tableName)) {
            String sql = "create table `uep-service`." + tableName + "(" +
                    "    id                int auto_increment" +
                    "        primary key," +
                    "    company_flag      char                                null comment '单位是否推送（0：推送；1：不推送）',\n" +
                    "    admin_flag        char                                null comment '学校管理员推送状态（0：推送；1：未推送）',\n" +
                    "    type              char(2)                             null comment '业务类型（1：招聘；2：宣讲会；3：空中宣讲会）',\n" +
                    "    matching          varchar(10)                         null comment '匹配度',\n" +
                    "    title             varchar(512) charset utf8           null comment '标题',\n" +
                    "    business_date     datetime                            null comment '业务实际（有效期、举办时间）',\n" +
                    "    push_type         char                                null comment '手动发送还是自动发送（1：学校发送、2：系统发送）',\n" +
                    "    push_date         datetime                            null comment '推送时间',\n" +
                    "    push_content      longtext charset utf8               null comment '推送内容',\n" +
                    "    position_matching varchar(1024)                       null comment '匹配情况',\n" +
                    "    read_flag         char      default '1'               null comment '是否已读（1：否；0：是）',\n" +
                    "    read_date         datetime                            null comment '阅读时间',\n" +
                    "    resume_flag       char      default '1'               null comment '是否发送简历（1：否；0：是）',\n" +
                    "    resume_date       datetime                            null comment '发送简历时间',\n" +
                    "    resume_file       varchar(512) charset utf8           null comment '简历地址',\n" +
                    "    student_id        int                                 null comment '学生编号',\n" +
                    "    business_id       int                                 null comment '业务编号',\n" +
                    "    company_id        int                                 null comment '公司编号',\n" +
                    "    create_time       timestamp default CURRENT_TIMESTAMP null comment '添加时间',\n" +
                    "    update_time       timestamp default CURRENT_TIMESTAMP null on update CURRENT_TIMESTAMP comment '编辑时间',\n" +
                    "    deleted           int       default 0                 null comment '逻辑删除 0正常 1删除',\n" +
                    "    cid               varchar(64)                         null comment '旧单位编号',\n" +
                    "    bid               varchar(64)                         null comment '久业务ID',\n" +
                    "    xh                varchar(32)                         null,\n" +
                    "    year_id           int                                 null comment '年份id',\n" +
                    "    old_id            varchar(64)                         null comment '原始编号id',\n" +
                    "    success_flag      char                                null comment '是否导入成功',\n" +
                    "    ability_flag      char                                null\n" +
                    ")\n" +
                    "    comment '消息推送表' charset = utf8mb4;\n";
            String indexSql = "create index type\n" +
                    "    on `uep-service`." + tableName + "(admin_flag, company_flag, type, business_id, deleted, xh);\n" +
                    "\n";
            try(Connection connection = dataSource.getConnection();
                Statement statement = connection.createStatement()) {
                statement.execute(sql);
                statement.execute(indexSql);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 根据表名插入数据
     * @param tableName
     * @param msg
     */
    public void dynamicInsertPushMsg(String tableName, PushMsg msg) {
        // 确保表存在
        createTableNotExist(tableName);
        try {
            baseMapper.dynamicInsert(tableName, msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 动态更新msg
     * @param tableName
     * @param msg
     */
    public void dynamicUpdate(String tableName, PushMsg msg) {
        baseMapper.dynamicUpdate(tableName, msg);
    }

    /**
     * 动态搜索
     * @param tableName
     * @param msg
     */
    public List<PushMsg> dynamicSelect(String tableName, PushMsg msg) {
        return baseMapper.dynamicSelect(tableName, msg);
    }

    /**
     * 查询近几年的数据
     * @param pushMsg
     * @return
     */
    private List<PushMsg> selectManyYearsPushMsg(PushMsg pushMsg) {
        Integer year = yearService.getYear().getId();
        List<PushMsg> result = new ArrayList<>();
        for (int i = 2; i > 0; i--) {
            String tableName = tableNamePrefix +(year - i);
            result.addAll(dynamicSelect(tableName, pushMsg));
        }
        return result;
    }

    @Override
    public JsonResult getAllPushCount(Integer year) {
        // 动态构建表名
        String tableName = tableNamePrefix + year;
        // 构建结果集
        Map<String, Long> result = new HashMap<>();
        // 查询本科消息总数
        PushMsgParam pushMsgParam = new PushMsgParam();
        pushMsgParam.setDegree("1");
        Long bksMsgCount = pushMsgMapper.dynamicSelectCount(tableName, pushMsgParam);
        result.put("bkstsl", bksMsgCount);
        // 查询本科生总浏览量
        pushMsgParam.setReadFlag("0");
        Long bksReadMsgCount = pushMsgMapper.dynamicSelectCount(tableName, pushMsgParam);
        result.put("bkslll", bksReadMsgCount);
        // 查询本科生发送简历量
        pushMsgParam.setReadFlag(null);
        pushMsgParam.setResumeFlag("0");
        Long bksResumeCount = pushMsgMapper.dynamicSelectCount(tableName, pushMsgParam);
        result.put("bksjll", bksResumeCount);


        // 查询本科消息总数
        pushMsgParam.setResumeFlag(null);
        pushMsgParam.setReadFlag(null);
        pushMsgParam.setDegree("2");
        Long yjsMsgCount = pushMsgMapper.dynamicSelectCount(tableName, pushMsgParam);
        result.put("yjstsl", yjsMsgCount);
        // 查询研究生总浏览量
        pushMsgParam.setReadFlag("0");
        Long yjsReadMsgCount = pushMsgMapper.dynamicSelectCount(tableName, pushMsgParam);
        result.put("yjslll", yjsReadMsgCount);
        // 查询研究生发送简历量
        pushMsgParam.setReadFlag(null);
        pushMsgParam.setResumeFlag("0");
        Long yjsResumeCount = pushMsgMapper.dynamicSelectCount(tableName, pushMsgParam);
        result.put("yjsjll", yjsResumeCount);


        return JsonResult.ok().setData(result);
    }

    @Override
    public JsonResult getCollegeAllPushCount(Integer year) {
        // 动态构建表名
        String tableName = tableNamePrefix + year;

        PushMsgParam pushMsgParam = new PushMsgParam();

        List<CollegeCountVO> result = new ArrayList<>();

        // 分组查询所有学院消息总数
        List<CollegeCountVO> msgCountList = pushMsgMapper.dynamicCollegeCount(tableName);


        // 查询已读的
        pushMsgParam.setReadFlag("0");
        List<CollegeCountVO> readCountList = pushMsgMapper.dynamicCollegeReadCount(tableName, pushMsgParam);

        // 查询已浏览的
        pushMsgParam.setReadFlag(null);
        pushMsgParam.setResumeFlag("0");
        List<CollegeCountVO> resumeCountList = pushMsgMapper.dynamicCollegeResumeCount(tableName, pushMsgParam);

        // 添加
        result.addAll(msgCountList);

        for (CollegeCountVO countVO: result) {
            for (CollegeCountVO readVO : readCountList) {
                if (countVO.getCollegeName().equals(readVO.getCollegeName())) {
                    countVO.setReadCount(readVO.getReadCount());
                }
            }
            for (CollegeCountVO resumeVO : resumeCountList) {
                if (countVO.getCollegeName().equals(resumeVO.getCollegeName())) {
                    countVO.setResumeCount(resumeVO.getResumeCount());
                }
            }
        }

        return JsonResult.ok().setData(result);
    }

    @Override
    public List<PushMsg> getAllPushMsg() {
        Integer year = yearService.getYear().getId();
        List<PushMsg> result = new ArrayList<>();
        for (int i = 1; i >= 0; i--) {
            String tableName = tableNamePrefix + (year - i);
            result.addAll(pushMsgMapper.getAllPushMsg(tableName));
        }
        // 过滤审核通过的数据, 并行流提高效率
        result = result.parallelStream()
                .filter(this::isApproved)
                .collect(Collectors.toList());
        return result;
    }

    /**
     * 判断pushMsg的审批状态
     * @param pushMsg
     * @return
     */
    private boolean isApproved(PushMsg pushMsg) {
        switch (pushMsg.getType()) {
            case "1":
                Recruit recruit = recruitService.getById(pushMsg.getBusinessId());
                return "1".equals(recruit.getState());
            case "2":
                Preach preach = preachService.getById(pushMsg.getBusinessId());
                return "1".equals(preach.getState());
            case "3":
                PreachCloud preachCloud = preachCloudService.getById(pushMsg.getBusinessId());
                return "1".equals(preachCloud.getState());
            default:
                return false;
        }
    }


}